/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package submarinesControl;

import java.util.Random;
import java.util.Scanner;
import model.Board;
import model.Square;

/**
 *
 * @author Karnit Genchay
 */
public class GameManager {
    // members
       private Player[] players ;
       private Player[] inActivePlayers ;
        private int numOfPlayers; 
        private Board [] boards;
        private int turn;
        private int nextTurn;
        private  final int SIZE_OF_BOARD;
        private boolean marks[][][][];
        private int numOfPlayerToAttack;
        public  String lastHit;
       private  boolean hitSubmarine;
        //    private boolean isValidInput = false; 
        //    Scanner scanner = new Scanner(System.in);  

    // public geters and setters
     
     public GameManager(int numOfPlayers,Player[] players,Player[] inActivePlayers,Board [] boards){
       this.players=players;
       this.inActivePlayers= inActivePlayers;
       this.numOfPlayers=numOfPlayers;
       this.boards = boards;
        this.turn =0;
        this.nextTurn=1;
        this.SIZE_OF_BOARD = boards[0].returnSizeOfBoard();
        this.marks = new boolean[numOfPlayers][numOfPlayers][SIZE_OF_BOARD][SIZE_OF_BOARD];
        this.hitSubmarine =false;
        //all marks are initialized with false automaticly
     }   
     
     public int getCurrentTurn() {
         return this.turn;
     }
     
     public void runGame(){
         boolean gameOver = false;

        while (!gameOver){
             play(players[turn]);//play menu  -  mark\bomb , quit game 
             
             if (numOfPlayers==1){
                 gameOver=true;
                 printWinner();
             }        
             turn=nextTurn;   
             nextTurn=(turn+1)%numOfPlayers;    
             isOut();
         }
     }
public void isOut(){
    for (int i = 0; i < numOfPlayers; i++) {
        if (boards[i].allSubsDown())
            leave(i);
    }
}
    public void play(Player player ){
        System.out.println("--------------------------------------------------------------------------------------------------------------");
        System.out.println("Turn of  " + player + ".    All the players boards:");
        printPlayersBoards();
        
        if(player.isHuman())
           humanPlay(player);
        else
            computerPlay(player);
        

    }
    public void computerPlay(Player player){
        
        Random rand = new Random();
//        boolean attackOver=false;
        int col;
        int row ;   
        numOfPlayerToAttack=turn;
        Square square;
      
//       while(!attackOver){
       col =  rand.nextInt(SIZE_OF_BOARD-1);
       row = rand.nextInt(SIZE_OF_BOARD-1);   
       lastHit = ""+(char)(col+'A')+(row+1);
        
       while(numOfPlayerToAttack==turn)
             numOfPlayerToAttack = rand.nextInt(numOfPlayers-1);
       
       square = boards[numOfPlayerToAttack] .getSquare(col, row);
       
       while(  boards[numOfPlayerToAttack].isAlreadyBombed(square)) 
             square = boards[numOfPlayerToAttack] .getSquare(col, row);

       hitSubmarine =boards[numOfPlayerToAttack].attack(square);    
//       }    
    }
public void humanPlay(Player player ){
int  input;

boolean turnOver = false;
 Scanner in = new Scanner(System.in);

while(!turnOver)
{
    System.out.println("Please choose action: ");
    System.out.println("1. Choose opponent ");
    System.out.println("2. Print all boards");
    System.out.println("3. Print my board");
    System.out.println("4. Leave game");
    
    input= in.nextInt();
    
    switch (input) {
        case 1:       
            turnOver= doMoveMenu(in);
            break;
        case 2:
            printPlayersBoards();
            break;
        case 3:
            player.printWithSubmarines();
            break;
        case 4:
             leave(turn);
            turnOver=true;
            break;
        default:
            throw new AssertionError();
    }
}
}
public boolean doMoveMenu(Scanner in){
    int action=0;
    boolean attackOver= false;
    Square square;
    int [] intArray;

            System.out.println("Choose player to attack (write his name):");
            numOfPlayerToAttack = AttackPlayer(  in.next() );   

            while(numOfPlayerToAttack==turn){
               System.out.println("Can't attack self! try again: "); 
               numOfPlayerToAttack = AttackPlayer(  in.next() );   
            }
            printBoard(numOfPlayerToAttack);    
            
            while(!attackOver){
            System.out.println("Choose action:");
            System.out.println("1. Choose square to attack:");
            System.out.println("2. Choose square to mark:");
            System.out.println("3. Choose square to unmark:");
            System.out.println("4. Back to main menu");
            action = in.nextInt();
            
                switch (action) {
                    case 1:
                        System.out.print("Attack square: ");
                        square = getSquare( numOfPlayerToAttack,in.next()) ;                  
                         while(    boards[numOfPlayerToAttack].isAlreadyBombed(square)){
                             System.out.print("Already bombed! try again: "); 
                             square = getSquare( numOfPlayerToAttack,in.next()) ;     
                         }      
                        attackOver = !boards[numOfPlayerToAttack].attack(square);
                        if(!attackOver)       
                                 System.out.println("You bombed a Submarine! You have another turn:");
                        printBoard(numOfPlayerToAttack);  
                        break;
                        
                    case 2:
                        System.out.print("Mark square: ");
                        intArray = boards[numOfPlayerToAttack].stringToIntArray(in.next());
                        //marks will be true in the index according to all relevant data
                        marks[turn][numOfPlayerToAttack][intArray[1]][intArray[0]] =true;
                        printBoardWithMarks(numOfPlayerToAttack);
                        break;
                        
                    case 3:
                        System.out.print("Unmark square: ");
                        intArray = boards[numOfPlayerToAttack].stringToIntArray(in.next());
                        marks[turn][numOfPlayerToAttack][intArray[1]][intArray[0]] =false;
                        printBoardWithMarks(numOfPlayerToAttack);
                        break;
                        
                    case 4:
                        return false;

                    default:
                        throw new AssertionError();
                }
            }
            
            return true;
}
private Square getSquare(int numOfPlayerToAttack,String s){
    return boards[numOfPlayerToAttack].getSquareByPositionString(s);
}
private void leave(int playerNum){
  //    System.out.println(player + " has left the game!");        
    for (int i = playerNum; i < numOfPlayers-1; i++) {
        players[i] = players[i+1];
        boards[i] = boards[i+1];
    }  
    players[numOfPlayers-1] =null;
    boards[numOfPlayers-1]=null;
    numOfPlayers--;  

}
        

    private int  AttackPlayer(String player) {
        int playerToAttack=-1;
        
        try{
        for (int i = 0; i < numOfPlayers; i++) 
            if (players[i].returnName().equals(player))
                playerToAttack = i;
        
        if(playerToAttack==-1)
            throw new IllegalArgumentException ();
        }catch  ( IllegalArgumentException  e){
       System.out.println("Illigal player's choice");
        throw new  RuntimeException(e);
        }
    return playerToAttack;
 }      
    private void printBoard(int i){
        boards[i].printSubmarinesDown();
        boards[i].print();
    }
    private void printPlayersBoards(){  
              for (int i = 0; i < numOfPlayers; i++) {
                  System.out.println(players[i]);
                  printBoard(i);
                  System.out.println("\t");
              }
    }
 private void printBoardWithMarks(int i){
     boards[i].printBoardWithMarks(marks[turn][i]);
 }  
   public void printWinner(){
       System.out.println("The winner is: "+players[0]);
   }  
public int getNumOfPlayers()
    {
        return numOfPlayers;                   
    }

    public void updateGame(String strPlayer, String strAttack, String strPosition, String strAction) {
        //attak player
        if(strAction.equals("bomb")){
            try {
                 if(players[turn].isHuman()){
                      for (int i = 0; i < numOfPlayers; i++) 
                         if(strAttack.equals(players[i].getName()))
                             numOfPlayerToAttack=i;
                  
                      Square square = players[numOfPlayerToAttack].getBoard().getSquareByPositionString(strPosition);
                      hitSubmarine=players[numOfPlayerToAttack].getBoard().attack(square);
                     lastHit = strPosition;
                     }
                 else
                    computerPlay(players[turn]);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        
        if (numOfPlayers==1){
//                 gameOver=true;
//                 printWinner();
             }   
        
        //if didn't hit - next turn
        if(!hitSubmarine){
             turn=nextTurn;   
             nextTurn=(turn+1)%numOfPlayers;    
        }
         isOut();

    }

    
    public String  []  moveData(){
        String []str= new String [4];
        int lastPlayer =(turn+numOfPlayers-1)%numOfPlayers;

//        str[0] = (hitSubmarine)?players[lastPlayer].getName():players[turn].getName();
        str[0] = players[turn].getName();
        str[1] = players[numOfPlayerToAttack].getName();
        str[2] = lastHit;
        str[3] = (hitSubmarine)?"hit!":"miss...";
                
        return str;
    }

    public boolean isCurrComputer() {
        return !players[turn].isHuman();
    }
}

